package com.ruoyi.web.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.jfinal.kit.StrKit;
import com.ruoyi.common.business.entity.YytMember;
import com.ruoyi.common.business.service.YytMemberService;
import com.ruoyi.common.business.service.YytTeamDonateLogService;
import com.ruoyi.common.group.service.YytGroupSkuOrderRelationService;
import com.ruoyi.common.oms.entity.YytOmsCartItem;
import com.ruoyi.common.oms.entity.YytOmsOrder;
import com.ruoyi.common.oms.entity.YytOmsPaymentInfo;
import com.ruoyi.common.oms.entity.YytOmsOrderItem;
import com.ruoyi.common.oms.service.YytOmsCartItemService;
import com.ruoyi.common.oms.service.YytOmsOrderItemService;
import com.ruoyi.common.oms.service.YytOmsOrderService;
import com.ruoyi.common.oms.service.YytOmsPaymentInfoService;
import com.ruoyi.common.pms.entity.YytPmsSkuInfo;
import com.ruoyi.common.pms.service.YytPmsSkuInfoService;
import com.ruoyi.common.sms.entity.YytSmsCoupon;
import com.ruoyi.common.sms.entity.YytSmsCouponHistory;
import com.ruoyi.common.sms.service.YytSmsCouponHistoryService;
import com.ruoyi.common.sms.service.YytSmsCouponService;
import com.ruoyi.common.ums.service.YytUmsGrowthChangeHistoryService;
import com.ruoyi.common.vip.service.YytVipMemberService;
import com.ruoyi.utils.CommonUtils;
import com.ruoyi.utils.LoginUtils;
import com.ruoyi.utils.RedisService;
import com.ruoyi.utils.ResponseResult;
import com.ruoyi.vo.WxPayBean;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.http.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户订单
 *
 * @author tanxingxian
 * @date 2021-12-24 09:18
 */
@RestController
@RequestMapping("/order")
public class OrderController extends AbstractWxPayApiController {
    public static Cache<String, String> applyCache = CacheBuilder.newBuilder().maximumSize(600).expireAfterWrite(60, TimeUnit.MINUTES).build();

    @Autowired
    private RedisService redisService;
    @Autowired
    private YytOmsOrderService yytOmsOrderService;
    @Autowired
    private YytOmsCartItemService yytOmsCartItemService;

    @Autowired
    private YytOmsPaymentInfoService yytOmsPaymentInfoService;

    @Autowired
    private YytOmsOrderItemService yytOmsOrderItemService;

    @Autowired
    private YytTeamDonateLogService yytTeamDonateLogService;

    @Autowired
    private YytPmsSkuInfoService yytPmsSkuInfoService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private YytSmsCouponHistoryService yytSmsCouponHistoryService;

    @Autowired
    private YytSmsCouponService yytSmsCouponService;

    @Autowired
    private YytMemberService yytMemberService;

    @Autowired
    private YytUmsGrowthChangeHistoryService yytUmsGrowthChangeHistoryService;

    @Autowired
    private YytVipMemberService yytVipMemberService;

    @Autowired
    private YytGroupSkuOrderRelationService yytGroupSkuOrderRelationService;

    @Autowired
    private WxPayBean wxPayBean;

    private String notifyUrl;
    private String refundNotifyUrl;

    @Override
    public WxPayApiConfig getApiConfig() {
        WxPayApiConfig apiConfig;

        try {
            apiConfig = WxPayApiConfigKit.getApiConfig(wxPayBean.getAppId());
        } catch (Exception e) {
            System.out.println("wxPayBean.getCertPath():" + wxPayBean.getCertPath());
            apiConfig = WxPayApiConfig.builder()
                    .appId(wxPayBean.getAppId())
                    .mchId(wxPayBean.getMchId())
                    .partnerKey(wxPayBean.getPartnerKey())
                    .certPath(wxPayBean.getCertPath())
                    .domain(wxPayBean.getDomain())
                    .build();
        }
        notifyUrl = apiConfig.getDomain().concat("/order/payNotify");
//        refundNotifyUrl = apiConfig.getDomain().concat("/order/refundNotify");
        return apiConfig;
    }

    /**
     * 获取用户全部订单
     */
    @GetMapping("/getOrders")
    public ResponseResult getAllOrders(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                                       @RequestParam("status") Integer status) {
        YytMember loginUser = LoginUtils.getLoginUser(redisService);
        return ResponseResult.success(yytOmsOrderService.getOrders(new Page<>(pageNum, 20), loginUser.getId(), status));
    }

    /**
     * 获取待付款和待收货订单数量
     */
    @GetMapping("/getOrderCount")
    public ResponseResult getOrderCount() {
        YytMember loginUser = LoginUtils.getLoginUser(redisService);
        // 待付款数量
        Integer unPayCount = yytOmsOrderService.countOrder(loginUser.getId(), 0);
        // 待收货数量
        Integer waitReceiveCount = yytOmsOrderService.countOrder(loginUser.getId(), 2);
        Map<String, Integer> result = new HashMap<>(2);
        result.put("unPayCount", unPayCount);
        result.put("waitReceiveCount", waitReceiveCount);
        return ResponseResult.success(result);
    }

    /**
     * 用户删除订单
     */
    @PostMapping("/deleteOrder")
    public ResponseResult deleteOrder(@RequestBody YytOmsOrder yytOmsOrder) {
        return ResponseResult.success(yytOmsOrderService.removeById(yytOmsOrder.getId()));
    }

    /**
     * 用户确认收货
     */
    @PostMapping("/confirmReceive")
    public ResponseResult confirmReceive(@RequestBody YytOmsOrder yytOmsOrder) {
        yytOmsOrder.setStatus(3);
        yytOmsOrder.setConfirmStatus(1);
        return ResponseResult.success(yytOmsOrderService.updateById(yytOmsOrder));
    }

    /**
     * 用户取消订单
     */
    @PostMapping("/cancelOrder")
    public ResponseResult cancelOrder(@RequestBody YytOmsOrder yytOmsOrder) {
        yytOmsOrder.setStatus(4);   // 已关闭
        return ResponseResult.success(yytOmsOrderService.updateById(yytOmsOrder));
    }

    /**
     * 用户下单
     */
    @PostMapping("/createOrder")
    public ResponseResult createOrder(@RequestBody YytOmsOrder yytOmsOrder, HttpServletRequest request) {
        YytMember loginUser = LoginUtils.getLoginUser(redisService);
        yytOmsOrder.setMemberId(loginUser.getId());
        yytOmsOrder.setMemberUsername(loginUser.getUsername());
        yytOmsOrderService.createOrder(yytOmsOrder);
        // 移除该用户的购物车对应商品
        List<String> skuIdList = new ArrayList<>();
        for (YytOmsOrderItem item : yytOmsOrder.getItemList()) {
            skuIdList.add(item.getSkuId());
        }
        yytOmsCartItemService.remove(new LambdaQueryWrapper<YytOmsCartItem>()
                .in(YytOmsCartItem::getProductSkuId, skuIdList).eq(YytOmsCartItem::getMemberId, loginUser.getId()));

        if (!yytOmsOrder.getOrderType().equals("1")){
            // redis放入订单 半个小时未支付关闭订单
            redisService.put("order:" + yytOmsOrder.getOrderSn(), CommonUtils.serialize(yytOmsOrder), 1800L);

            if(StringUtils.isNotBlank(yytOmsOrder.getCouponId())) {
                yytSmsCouponHistoryService.getUpdateCoupon(yytOmsOrder);
            }
        }else {
            // 减库存
            yytPmsSkuInfoService.reduceInventory(yytOmsOrder.getId());
            // 减少会员送菜次数
            yytVipMemberService.reduceNumber(loginUser.getId());

            return ResponseResult.success("选菜成功");
        }


        String orderSn = yytOmsOrder.getOrderSn();
        String orderId = yytOmsOrder.getId();
        String totalAmount = yytOmsOrder.getTotalAmount().toString();

        BigDecimal bFee = new BigDecimal(totalAmount).multiply(new BigDecimal(100));
        if (loginUser.getId().equals("1547747634506354689") ){
            bFee = BigDecimal.valueOf(1);
        }



        String openid = loginUser.getWechatId();

        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        WxPayApiConfigKit.putApiConfig(getApiConfig());
        WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
        String tradeno = WxPayKit.generateStr();
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body("农博园商城收款")
                .attach("农博园")
                .out_trade_no(tradeno)
                .total_fee(String.valueOf(bFee.intValue()))
//                .total_fee("1")
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openid)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, params);

//        log.info(xmlResult);
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");

        if (!WxPayKit.codeIsOk(returnCode)) {
//            return new AjaxResult().addError();
            return ResponseResult.failure(returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            return ResponseResult.failure(returnMsg);

        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");

        Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(wxPayApiConfig.getAppId(), prepayId,
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
        String jsonStr = JSON.toJSONString(packageParams);
        System.out.println("jsonStr" + jsonStr);
//        log.info("小程序支付的参数:" + jsonStr);
        applyCache.put(tradeno, orderId + "#" + orderSn + "#" + totalAmount);
        JSONObject object = new JSONObject();
        JSONObject object1 = new JSONObject();
        YytOmsPaymentInfo yytOmsPaymentInfo = new YytOmsPaymentInfo();
        yytOmsPaymentInfo.setOrderId(orderId);
        yytOmsPaymentInfo.setOrderSn(orderSn);
        yytOmsPaymentInfo.setAlipayTradeNo(tradeno);
        yytOmsPaymentInfo.setTotalAmount(new BigDecimal(totalAmount));
//        yytOmsPaymentInfo.setTotalAmount(new BigDecimal("0.01"));
        yytOmsPaymentInfo.setSubject("亿器互联");
        yytOmsPaymentInfo.setPaymentStatus("0");
        yytOmsPaymentInfo.setCreateTime(java.time.LocalDateTime.now());
        yytOmsPaymentInfo.setCallbackContent(jsonStr);
        yytOmsPaymentInfo.setCallbackTime(java.time.LocalDateTime.now());
        yytOmsPaymentInfoService.save(yytOmsPaymentInfo);
        if(StringUtils.isNotBlank(yytOmsOrder.getCouponId()) && StringUtils.isNotBlank(String.valueOf(yytOmsOrder.getCouponAmount()))){
            object.put("couponId", yytOmsOrder.getCouponId());
            object.put("couponAmount", yytOmsOrder.getCouponAmount());
        }
        object.put("orderId", orderId);
        object.put("orderSn", orderSn);
        object.put("memberId", loginUser.getId());
        object.put("out_trade_no", tradeno);
        object.put("id", yytOmsOrder.getId());
        object1.put("user", object);
        object1.put("jsonStr", jsonStr);
        return ResponseResult.success(object1);
    }

    /**
     * 支付成功通知
     */
    @GetMapping("/payNotify")
    public ResponseResult wxpayNotify(HttpServletRequest request) {
        String orderId = request.getParameter("orderId");
        String orderSn = request.getParameter("orderSn");
        String id = request.getParameter("id");
        String couponId = request.getParameter("couponId");
        String alipayTradeNo = request.getParameter("out_trade_no");
        QueryWrapper<YytOmsPaymentInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", orderId).eq("order_sn", orderSn).eq("alipay_trade_no", alipayTradeNo);
        List<YytOmsPaymentInfo> list = yytOmsPaymentInfoService.list(wrapper);
        YytOmsPaymentInfo yytOmsPaymentInfo = new YytOmsPaymentInfo();
        yytOmsPaymentInfo.setPaymentStatus("1");
        yytOmsPaymentInfo.setConfirmTime(java.time.LocalDateTime.now());
        yytOmsPaymentInfo.setId(list.get(0).getId());
        yytOmsPaymentInfoService.updateById(yytOmsPaymentInfo);

        // 给用户添加成长值
        yytUmsGrowthChangeHistoryService.addUserIntegral(orderId);

        // 判断是否是捐赠订单
        yytTeamDonateLogService.addTeamOrder(orderId);

        // 判断是否拼团订单
        yytGroupSkuOrderRelationService.isGroupOrder(orderId);

        YytOmsOrder yytOmsOrder = new YytOmsOrder();
        yytOmsOrder.setId(id);
        yytOmsOrder.setStatus(1);
        yytOmsOrder.setPayType(2);
        yytOmsOrder.setPaymentTime(LocalDateTime.now());
        yytOmsOrderService.updateById(yytOmsOrder);

        // 计算返利金额
        yytMemberService.getCountRebate(orderId, request.getParameter("memberId"));


        // 减库存
        yytPmsSkuInfoService.reduceInventory(orderId);
        // 修改优惠券状态
        if(StringUtils.isNotBlank(couponId)){
            String[] strings = couponId.split(",");

            List<String> hisList = new ArrayList<>();
            hisList.add("1569985866041880577");
            hisList.add("1569985596788535298");
            hisList.add("1569985087897825281");
            hisList.add("1569966862833250306");
            for (String ids : strings){
                UpdateWrapper<YytSmsCouponHistory> wrapper1 = new UpdateWrapper<>();
                YytSmsCouponHistory history = yytSmsCouponHistoryService.getById(ids);
                if (hisList.contains(history.getCouponId())){
                    if (history.getBalance().compareTo(new BigDecimal(0)) == 0){
                        wrapper1.eq("id", ids)
                                .set("use_type", 1)
                                .set("use_time", LocalDateTime.now())
                                .set("order_id", yytOmsOrder.getId())
                                .set("order_sn", yytOmsOrder.getOrderSn());
                        yytSmsCouponHistoryService.update(wrapper1);
                        YytSmsCouponHistory smsCoupon = yytSmsCouponHistoryService.getById(ids);
                        UpdateWrapper<YytSmsCoupon> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.setSql("use_count = use_count + 1").eq("id", smsCoupon.getCouponId());
                        yytSmsCouponService.update(updateWrapper);
                    }
                }else{
                    wrapper1.eq("id", ids).set("use_mode", 0).set("use_type", 1).set("use_time", LocalDateTime.now()).set("order_id", orderId).set("order_sn", orderSn);
                    yytSmsCouponHistoryService.update(wrapper1);
                    YytSmsCouponHistory smsCoupon = yytSmsCouponHistoryService.getById(ids);
                    UpdateWrapper<YytSmsCoupon> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.setSql("use_count = use_count + 1").eq("id", smsCoupon.getCouponId());
                    yytSmsCouponService.update(updateWrapper);
                }
            }
        }
        return ResponseResult.success("支付成功！");
    }

    /**
     * 获取用户本月订单数量 待发货.已发货.已完成
     */
    @GetMapping("/monthOrderNum")
    public ResponseResult monthOrderNum() {
        YytMember loginUser = LoginUtils.getLoginUser(redisService);
        LambdaQueryWrapper<YytOmsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(YytOmsOrder::getStatus, '0');
        wrapper.ne(YytOmsOrder::getStatus, '4');
        wrapper.ne(YytOmsOrder::getStatus, '5');
        wrapper.eq(YytOmsOrder::getMemberId, loginUser.getId());
        // 因为是查本月，所以当前时间不会在下个月的时间 直接大于本月1号即可
        wrapper.ge(YytOmsOrder::getCreateTime, LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()));
        return ResponseResult.success(yytOmsOrderService.count(wrapper));
    }

    /**
     * 根据订单id获取订单详情信息
     */
    @GetMapping("/getInfo")
    public ResponseResult getInfo(@RequestParam("orderId") String orderId) {
        YytMember loginUser = LoginUtils.getLoginUser(redisService);
        return ResponseResult.success(yytOmsOrderService.getOrderInfo(orderId, loginUser.getId()));
    }

    /**
     * 根据用户id 获取订单类型
     * @param memberId
     * @return
     */
    @GetMapping("/getOrderInfoType")
    public ResponseResult getOrderInfoType(@RequestParam("memberId") String memberId,
                                            @RequestParam("orderId") String orderId
                                            ){
        Integer infoType = yytOmsCartItemService.getOrderInfoType(orderId, memberId);

        return ResponseResult.success(infoType);
    }

    /**
     * 把未支付的订单号投递到消息队列
     * @param orderId
     */
    @GetMapping("/addOrderMessageQueue")
    public ResponseResult addOrderMessageQueue(String orderId){
        boolean status = yytOmsOrderService.orderMessageQueue(orderId);
        return ResponseResult.success(status);
    }

    /**
     * 从redis中获取key对应的过期时间;
     * 如果该值有过期时间，就返回相应的过期时间;
     * 如果该值没有设置过期时间，就返回-1;
     * 如果没有该值，就返回-2;
     */
    @GetMapping("/getRedisCountDown")
    public ResponseResult getRedisCountDown(@RequestParam("orderId") String orderId){
        String key = "order:" + orderId + "";
        Long expire = stringRedisTemplate.opsForValue().getOperations().getExpire(key);
        System.out.println(expire);

        return ResponseResult.success(expire);
    }


    /**
     * 店铺管理当日订单数
     * @return
     */
    @GetMapping("/getDayCountNumber")
    public ResponseResult getDayCountNumber(@RequestParam("dayDate") String dayDate){
        return ResponseResult.success(yytOmsOrderService.getDayCountNumber(dayDate));
    }

    /**
     * 获取今日数据列表
     * @return
     */
    @GetMapping("/getDayOrderListTitle")
    public ResponseResult getDayOrderListTitle(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                                               @RequestParam("dayDate") String dayDate
                                               ){
        return ResponseResult.success(yytOmsOrderService.getDayOrderListTitle(new Page<>(pageNum, 20), dayDate));
    }

    /**
     * 根据店铺获取店铺今日订单数据
     * @param shopId
     * @return
     */
    @GetMapping("/getShopDayOrderList")
    public ResponseResult getShopDayOrderList(@RequestParam("shopId") String shopId,
                                              @RequestParam("dayDate") String dayDate
                                              ){
        return ResponseResult.success(yytOmsOrderService.getShopDayOrderList(shopId, dayDate));
    }

    /**
     * 修改订单状态
     * @param orderId
     * @return
     */
    @GetMapping("/updateOrderService")
    public ResponseResult updateOrderService(@RequestParam("orderId") String orderId){
        return ResponseResult.success(yytOmsOrderService.updateOrderStatus(orderId));
    }

    /**
     * 获取订单状态
     * @param order
     * @return
     */
    @GetMapping("/getOrderStatus")
    public ResponseResult getOrderStatus(@RequestParam("orderId") String order){
        return ResponseResult.success(yytOmsOrderService.getById(order));
    }

    /**
     * 获取本人当月订单
     * @return
     */
    @GetMapping("/getMyMonthOrder")
    public ResponseResult getMyMonthOrder(){
        YytMember loginUser = LoginUtils.getLoginUser(redisService);
        return ResponseResult.success(yytOmsOrderService.getMyMonthOrders(loginUser.getId()));
    }

    /**
     * 待核销订单
     * @return
     */
    @GetMapping("/getAwaitOrderCancel")
    public ResponseResult getAwaitOrderCancel(){
        YytMember loginUser = LoginUtils.getLoginUser(redisService);
        return ResponseResult.success(yytOmsOrderService.getAwaitOrderCancel(loginUser.getId()));
    }


    /**
     * 判断库存是否足够
     * @param skuInfoList
     * @return
     */
    @PostMapping("/isEnoughStatus")
    public ResponseResult isEnoughStatus(@RequestBody List<YytPmsSkuInfo> skuInfoList){
        for (YytPmsSkuInfo ys : skuInfoList){
            YytPmsSkuInfo skuInfo = yytPmsSkuInfoService.getById(ys.getSkuId());
            if(skuInfo.getInventory() < ys.getQuantity()){
                return ResponseResult.success(false);
            }
        }
        return ResponseResult.success(true);
    }

}
